#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
//#include <SDL/include/SDL.h>
#include <SDL.h>

#include "avsdeclib.h"

#define BUFLEN   1024*1024*3
//#define S_WIDTH   352
//#define S_HEIGHT  288


#define S_WIDTH   720
#define S_HEIGHT  576

static SDL_Surface *screen;

static void video_write(SDL_Overlay * yuv_overlay,
			BYTE * pY, BYTE * pU, BYTE * pV,
			int width, int height, SDL_Rect * pRect)
{
	int i;
	if (pY == NULL || pU == NULL || pV == NULL)
		return;

	/* Lock SDL_yuv_overlay */
	if (SDL_MUSTLOCK(screen)) {
		if (SDL_LockSurface(screen) < 0)
			return;
	}
	if (SDL_LockYUVOverlay(yuv_overlay) < 0)
		return;

	/* let's draw the data (*yuv[3]) on a SDL screen (*screen) */
	/* deal with border stride */
	/* reverse u and v for SDL */
	for (i = 0; i < yuv_overlay->h; i++) {
		memcpy(yuv_overlay->pixels[0] +
		       yuv_overlay->pitches[0] * i, pY + width * i,
		       yuv_overlay->w);
	}
	for (i = 0; i < yuv_overlay->h / 2; i++) {
		memcpy(yuv_overlay->pixels[1] +
		       yuv_overlay->pitches[1] * i, pV + width * i / 2,
		       yuv_overlay->w / 2);
		memcpy(yuv_overlay->pixels[2] +
		       yuv_overlay->pitches[2] * i, pU + width * i / 2,
		       yuv_overlay->w / 2);
	}

	/* Unlock SDL_yuv_overlay */
	if (SDL_MUSTLOCK(screen)) {
		SDL_UnlockSurface(screen);
	}
	SDL_UnlockYUVOverlay(yuv_overlay);

	/* Show, baby, show! */
	SDL_DisplayYUVOverlay(yuv_overlay, pRect);
}


int main(int argc, char ** argv)
{
	///////////////////////////////////////////
	//var
	///////////////////////////////////////////
	//balabala
	BYTE * buf, * pData;
	int len, leftLen;
	int frameLen, noUseDataLen;
	SEQ_INFO info;
	BYTE *pY, *pU, *pV;
	FILE *fp;
	//sdl
	SDL_Overlay *yuv_overlay;
	SDL_Rect rect;
	SDL_Event event;
	///////////////////////////////////////////
	//init
	///////////////////////////////////////////
	//args init
	if (argc != 2) {
		printf("usage: %s *.avs\n", argv[0]);
		return 0;
	}
	//avs codec init
	fp = fopen(argv[1], "rb");
	if (!fp) {
		perror("fopen");
		return 0;
	}
	InitAVSDec();
	buf = (BYTE *) malloc(sizeof(BYTE) * BUFLEN);
	len = fread(buf, 1, 30000, fp);
	if(GetSeqInfo(buf,30000,&info)!=1)
		printf("Can't determing AVSseq info.....\n");
	leftLen = len;
	pData = buf;
	//sdl init
	putenv("SDL_VIDEO_YUV_HWACCEL=0");
	putenv("SDL_VIDEO_X11_NODIRECTCOLOR=0");
	SDL_Init(SDL_INIT_VIDEO);
	atexit(SDL_Quit);
	screen = SDL_SetVideoMode(info.image_width, info.image_height, 0,
				  SDL_SWSURFACE);
	if (screen == NULL) {
		fprintf(stderr, "Unable to set %dx%d video: %s\n",
			info.image_width, info.image_height,
			SDL_GetError());
		exit(1);
	}
	yuv_overlay = SDL_CreateYUVOverlay(info.image_width,
							info.image_height,
							SDL_YV12_OVERLAY,
							screen);
	if (yuv_overlay == NULL) {
		fprintf(stderr,
			"SDL: Couldn't create SDL_yuv_overlay: %s\n",
			SDL_GetError());
		exit(1);
	}
	rect.x = 0;
	rect.y = 0;
	rect.w = info.image_width;
	rect.h = info.image_height;
	SDL_DisplayYUVOverlay(yuv_overlay, &rect);
	///////////////////////////////////////////////////
	//main loop
	///////////////////////////////////////////////////
	do {
		SDL_PollEvent(&event);
		switch (event.type) {
			case SDL_KEYDOWN:
				if (event.key.keysym.sym != SDLK_ESCAPE)
					break;
				/* Otherwise, let's continue */
			case SDL_QUIT:
				goto Exit_Player;
			default:
				break;
		}
		if (GetOneFrameBitsFromBuffer(
				pData, (int) leftLen,
				(int *) &frameLen,
				(int *) &noUseDataLen) != 1) {
			memcpy(buf, buf + (len - leftLen), leftLen);
			if ((len = fread(buf + leftLen, 1, 
			                 BUFLEN - leftLen, fp)) <= 0)
				break;
			len += leftLen;
			leftLen = len;
			pData = buf;
			continue;
		}
		DecOneFrameFromBuffer(pData + noUseDataLen, frameLen, &pY,
				      &pU, &pV);
		video_write(yuv_overlay, pY, pU, pV, info.image_width,
			    info.image_height, &rect);
		pData += frameLen;
		leftLen -= frameLen;
	} while ((*(DWORD *) pData) != SEQENCE_END_CODE);
	/////////////////////////////////////////////////////
	//exit...
	/////////////////////////////////////////////////////
Exit_Player:
	fclose(fp);
	free(buf);
	return 0;
}
